////package com.sky.module.support.log.aspect;
////
////
////import cn.hutool.core.convert.Convert;
////import cn.hutool.core.util.StrUtil;
////import cn.hutool.core.util.URLUtil;
////import cn.hutool.extra.servlet.ServletUtil;
////import com.alibaba.fastjson.JSON;
////import com.alibaba.fastjson.JSONObject;
////
//////import io.swagger.annotations.Api;
////import com.google.protobuf.Api;
////import com.sky.module.support.log.dto.OptLogDTO;
////import com.sky.module.support.log.event.SysLogEvent;
////import com.sky.module.system.utils.IpUtil;
////import com.sky.module.system.OperLog.domain.entity.SysOperLog;
////import com.sky.module.system.user.domain.entity.User;
////import lombok.extern.slf4j.Slf4j;
////import org.aspectj.lang.JoinPoint;
////import org.aspectj.lang.ProceedingJoinPoint;
////import org.aspectj.lang.annotation.*;
////import org.junit.Before;
////import org.springframework.beans.factory.annotation.Autowired;
////import org.springframework.context.ApplicationContext;
////import org.springframework.security.core.context.SecurityContextHolder;
////import org.springframework.web.context.request.RequestAttributes;
////import org.springframework.web.context.request.RequestContextHolder;
////import org.springframework.web.context.request.ServletRequestAttributes;
////
////import javax.servlet.http.HttpServletRequest;
////import java.time.LocalDateTime;
////import java.time.temporal.ChronoUnit;
////import java.util.Arrays;
////import java.util.Objects;
////import java.util.function.Consumer;
////
/////**
//// * 操作日志使用spring event异步入库
//// */
////@Slf4j
////@Aspect
////public class SysLogAspect {
////
////    /**
////     * 事件发布是由ApplicationContext对象管控的，我们发布事件前需要注入ApplicationContext对象调用publishEvent方法完成事件发布
////     **/
////    @Autowired
////    private ApplicationContext applicationContext;
////
////
////    /***
////     * 定义controller切入点拦截规则，拦截SysLog注解的方法
////     */
////    @Pointcut("@annotation(com.sky.module.support.log.annotation.SysLog)")
////    public void sysLogAspect() {
////
////    }
////
////
////    // 只要有这个注解的就切入
//////    @Before("sysLogAspect()")
//////    public void recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
//////        tryCatch((val) -> {
//////
////////            final Object proceed = joinPoint.proceed();
//////        });
//////    }
////
////    /***
////     * @description 环绕通知
////     *
////     * @return void
////     * @date 2023/3/8 1:22
////     *
////     */
////    @Around("sysLogAspect()")
////    public void collectionLog(ProceedingJoinPoint joinPoint) {
////        // 大try catch
////        tryCatch((val) -> {
////            RequestAttributes ra = RequestContextHolder.getRequestAttributes();
//            ServletRequestAttributes sra = (ServletRequestAttributes) ra;
////            HttpServletRequest request = sra.getRequest();
////
////            // *========数据库日志=========*//
////            SysOperLog operLog = new SysOperLog();
////            //状态
////            operLog.setStatus(1);
////
////            // 请求的地址
////            String ip = IpUtil.getIpAddress(request);//IpUtil.getIpAddr(ServletUtils.getRequest());
////            operLog.setOperIp(ip);
////            operLog.setOperUrl(request.getRequestURI());
////
////            String token = request.getHeader("token");
////            String userName = JwtHelper.getUsername(token);
////            operLog.setOperName(userName);
////
////            if (e != null) {
////                operLog.setStatus(0);
////                operLog.setErrorMsg(e.getMessage());
////            }
////
////            // 设置方法名称
////            String className = joinPoint.getTarget().getClass().getName();
////            String methodName = joinPoint.getSignature().getName();
////            operLog.setMethod(className + "." + methodName + "()");
////
////            // 设置请求方式
////            operLog.setRequestMethod(request.getMethod());
////
////            // 处理设置注解上的参数
////            getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
////
////        });
////    }
////
////    /***
////     * @description 消费者
////     * @param consumer
////     * @return void
////     * @date 2023/3/8 1:20
////     *
////     */
////    private void tryCatch(Consumer<String> consumer) {
////        try {
////
////            consumer.accept("");
////        } catch (Exception e) {
////            // 全部异常在这
////            log.warn("记录操作日志异常", e);
////        }
////    }
////
////    /**
////     * 返回通知
////     *
////     * @param ret
////     * @throws Throwable
////     */
////    @AfterReturning(returning = "ret", pointcut = "sysLogAspect()")
////    public void doAfterReturning(Object ret) {
////        //
////        tryCatch((aaa) -> {
////            //  转换
////            R r = Convert.convert(R.class, ret);
////            // 从线程上下文中获取到 log 对象
////            OptLogDTO sysLog = get();
////
////            // 如果r 为空的话
////            if (r == null) {
////                sysLog.setType("OPT");
////            } else {
////                // 如果r不为空
////                if (r.getIsSuccess()) {
////                    //  说明当前是操作日志
////                    sysLog.setType("OPT");
////                } else {
////                    // 说明当前是ex 日志
////                    sysLog.setType("EX");
////                    sysLog.setExDetail(r.getMsg());
////                }
////                sysLog.setResult(getText(r.toString()));
////            }
////
////            // 然后发布事件 发布事件以后，监听器去监听
////            publishEvent(sysLog);
////        });
////
////    }
////
////    private void publishEvent(OptLogDTO sysLog) {
////        // 设置方法执行完成时间
////        sysLog.setFinishTime(LocalDateTime.now());
////        // 设置消费时间
////        sysLog.setConsumingTime(sysLog.getStartTime().until(sysLog.getFinishTime(), ChronoUnit.MILLIS));
////        // 发布事件，将log对象包装成 事件对象，发布出去
////        applicationContext.publishEvent(new SysLogEvent(sysLog));
////        // 防止内存泄漏，及时移除线程上下文保存的对象
////        THREAD_LOCAL.remove();
////    }
////
////    /**
////     * 异常通知
////     *
////     * @param e
////     */
////    @AfterThrowing(pointcut = "sysLogAspect()", throwing = "e")
////    public void doAfterThrowable(Throwable e) {
////        // 如果执行过程中，发现了异常
////        tryCatch((aaa) -> {
////            // 从当前上下文中获取到log 对象
////            OptLogDTO sysLog = get();
////            // 设置log信息的类型
////            sysLog.setType("EX");
////
////            // 异常对象
////            // 设置详细信息
////            sysLog.setExDetail(LogUtil.getStackTrace(e));
////            // 异常信息
////            sysLog.setExDesc(e.getMessage());
////            // 然后发布事件， 至于这个消息发布出去以后，其它人怎么处理，我们这里发布事件的生产者我们不管
////            //  是将消息持久化到数据库，还是直接将消息打印到控制台，还是直接返回给前端我们根本不管,
////            // 这样子就可以达到一个解耦的效果, 也就是代码没用写到一起
////            //
////            publishEvent(sysLog);
////        });
////    }
////
////    /**
////     * 截取指定长度的字符串
////     *
////     * @param val
////     * @return
////     */
////    private String getText(String val) {
////        return StrUtil.sub(val, 0, 65535);
////    }
////
//////    @Around("@annotation(sLog)")
//////    @SneakyThrows
//////    public Object around(ProceedingJoinPoint point, SysLog sLog) {
//////        log.info("当前线程id={}", Thread.currentThread().getId());
//////
//////        String strClassName = point.getTarget().getClass().getName();
//////        String strMethodName = point.getSignature().getName();
//////
//////        log.info("[类名]:{},[方法]:{}", strClassName, strMethodName);
//////        Log sysLog = Log.builder().build();
//////
//////        // 开始时间
//////        Long startTime = Instant.now().toEpochMilli();
//////        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
//////        BaseContextHandler.getAccount();
//////        sysLog.setCreateUser(BaseContextHandler.getUserId());
//////        sysLog.setRequestIp(ServletUtil.getClientIP(request));
//////        sysLog.setUserName(BaseContextHandler.getNickName());
//////        sysLog.setDescription(LogUtil.getControllerMethodDescription(point));
//////
//////        // 类名
//////        sysLog.setClassPath(point.getTarget().getClass().getName());
//////        //获取执行的方法名
//////        sysLog.setActionMethod(point.getSignature().getName());
//////        sysLog.setRequestUri(URLUtil.getPath(request.getRequestURI()));
//////        sysLog.setHttpMethod(HttpMethod.get(request.getMethod()));
//////        // 参数
//////        Object[] args = point.getArgs();
//////        sysLog.setParams(getText(JSONObject.toJSONString(args)));
//////
//////        sysLog.setStartTime(LocalDateTime.now());
//////        sysLog.setUa(request.getHeader("user-agent"));
//////
//////        // 发送异步日志事件
//////        Object obj = point.proceed();
//////
//////        R r = Convert.convert(R.class, obj);
//////        if (r.getIsSuccess()) {
//////            sysLog.setType(LogType.OPT);
//////        } else {
//////            sysLog.setType(LogType.EX);
//////            sysLog.setExDetail(r.getMsg());
//////        }
//////        if (r != null) {
//////            sysLog.setResult(getText(r.toString()));
//////        }
//////
//////        sysLog.setFinishTime(LocalDateTime.now());
//////        long endTime = Instant.now().toEpochMilli();
//////        sysLog.setConsumingTime(endTime - startTime);
//////
//////        applicationContext.publishEvent(new SysLogEvent(sysLog));
//////        return obj;
//////    }
////
////
////}
